package controls
{
	import com.adobe.crypto.MD5;
	import com.adobe.crypto.SHA1;
	import flash.utils.ByteArray;
	import mx.utils.SHA256;
	/**
	 * 
	 * Provides an all static API which wraps the SHA1, SHA-256 and 
	 * MD5 encryption algorithms, respectively, in order to allow a 
	 * supported encryption algorithm to be applied to a String with or without salt
	 * 
	 * @see com.adobe.crypto.MD5
	 * @see com.adobe.crypto.SHA1
	 * @see mx.utils.SHA256
	 * @see flash.utils.ByteArray;
	 * 
	 */    
	public final class Encryption
	{
		/**
		 * 
		 * Defines the constant which represents an SHA-256 hash 
		 * algorithm 
		 * 
		 */
		public static const CRYPTIT_SHA256:String = "SHA-256";
		
		/**
		 * 
		 * Defines the constant which represents a US Secure 
		 * Hash Algorithm 1 (SHA1)
		 * 
		 */
		public static const CRYPTIT_SHA1:String   = "SHA1";
		
		/**
		 * 
		 * Defines the constant which represents an MD5 Message
		 * Digest Algorithm
		 * 
		 */
		public static const CRYPTIT_MD5:String    = "MD5";
		
		/**
		 * 
		 * Provides a utility operation from which a String is encrypted
		 * to the specified encryption with or without salt
		 * 
		 * @example the following example demonstrates each Encryption
		 * type being performed on the same String
		 * 
		 * <listing version="3.5">
		 * 
		 * var password:String = "iamboredsoiblog";
		 * 
		 * 
		 * without SALT
		 * trace( Encryption.encrypt( password, Encryption.CRYPTIT_MD5 ) );
		 * //
		 * 
		 * trace( Encryption.encrypt( password, Encryption.CRYPTO_SHA1 ) );
		 * //
		 * 
		 * trace( Encryption.encrypt( password, Encryption.CRYPTO_SHA256) );
		 * // 
		 * </listing>
		 * 
		 * @param  the String which is to be encrypted
		 * @param  a constant representing the required encryption
		 * @param use salt or not on the encryption
		 * @param lenght of the salt
		 * @return an encrypted version of the source parameter
		 * 
		 * 
		 */        
		public static function encrypt(source:String, type:String, UseSalt:Boolean = false, SaltLenght:Number=10) : String
		{
			var encryption:String;
			
			var strSalt:String = GenerateSalt(SaltLenght);
			
			if(UseSalt==true){
				source = strSalt+""+source+""+strSalt;
			}
			
			switch ( type )
			{
				case CRYPTIT_MD5:
					encryption = MD5.hash( source );
					break;
				case CRYPTIT_SHA1:
					encryption = SHA1.hash( source );
					break;
				case CRYPTIT_SHA256:
					var ba:ByteArray = new ByteArray();
					ba.writeUTFBytes( source )
					encryption = SHA256.computeDigest( ba );
					break; 
			}
			
			if(UseSalt==true){
				encryption = encryption+":"+strSalt;
			}            
			
			return encryption;
		}
		
		
		/**
		 * @param the String which is to be checked on encrypted password
		 * @param the encrypted password
		 * @param used or no used salt
		 * @return true or false
		 */         
		
		public static function CheckCrypt(pw:String, encrpw:String, type:String, UseSalt:Boolean = false) : Boolean
		{
			var decryption:String;
			
			if(UseSalt==true){
				var parts:Array = encrpw.split( ':' );
				var strSalt:String = parts[1];
				pw = strSalt+""+pw+""+strSalt;
			}
			
			switch ( type )
			{
				case CRYPTIT_MD5:
					decryption = MD5.hash( pw );
					break;
				case CRYPTIT_SHA1:
					decryption = SHA1.hash( pw );
					break;
				case CRYPTIT_SHA256:
					var ba:ByteArray = new ByteArray();
					ba.writeUTFBytes( pw )
					decryption = SHA256.computeDigest( ba );
					break; 
			}
			
			if(UseSalt==true){
				decryption = decryption+":"+strSalt;
			}
			
			if(decryption==encrpw){
				return true;
			}else{
				return false;
			}
			//return decryption;
		}
		
		
		public static function GenerateSalt(maxchars:Number = 15):String{
			var randomChar:Array = ['number', 'letter'];
			
			var pass:String = "";
			
			var i:int = 0;
			for (i; i<maxchars; i++)
			{
				//Runs a loop according to the maximum amount of chars
				var num:Number = Math.floor(Math.random()*(3-1));
				//Random number between 3 and 0
				if (randomChar[num] == 'number') {
					//if the char will be a number
					pass += ''+Math.floor(Math.random()*(10-1))+'';
					//add a number to finalString between 0 and 10
				} else {
					//If letter
					pass += String.fromCharCode(Math.floor(Math.random()*(90-65))+65);
					//add a letter from A-Z
				}
			}
			return pass;
			
		}
		
	}
}